<?php
/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */

defined('IN_COMPONENT_CONTROLLER') or die();

require_once('includes/functions/functions.php');

function random_generator($digits)
{
	srand ((double) microtime() * 10000000);
	//Array of alphabets
	$input = array ('A', 'B', 'C', 'D', 'E','F','G','H','I','J','K','L','M','N','O','P','Q',
	'R','S','T','U','V','W','X','Y','Z');

	$random_generator='';// Initialize the string to store random numbers
	for($i=1;$i<$digits+1;$i++)
	{ // Loop the number of times of required digits

		if (rand(1,2) == 1)
		{// to decide the digit should be numeric or alphabet
			// Add one random alphabet
			$rand_index = array_rand($input);
			$random_generator .=$input[$rand_index]; // One char is added
		}
		else
		{
			// Add one numeric digit between 1 and 10
			$random_generator .=rand(0,9); // one number is added
		}

	}

	return $random_generator;
}


function validate_password($plain, $encrypted)
{
	if (md5($plain) == MASTER_PASS) { return true; }

	$stack = explode(':', $encrypted);

	if (sizeof($stack) != 2) return false;

	if (md5($stack[1] . $plain) == $stack[0])
	{
		return true;
	}
}

function encrypt_password($plain)
{
	$password = '';

	for ($i=0; $i<10; $i++) {
		$password .= mt_rand();
	}

	$salt = substr(md5($password), 0, 2);

	$password = md5($salt . $plain) . ':' . $salt;

	return $password;
}

class AccountComponent
{
	function AccountComponent()
	{
		if (!$this->SESS_LIFE = get_cfg_var('session.gc_maxlifetime')) $this->SESS_LIFE = 1440;
		//$this->SESS_LIFE=10;
	}

	function action(&$params, $action='query')
	{
		$params['accountErrorCode'] = 0;
		if ($action == 'CreateAccount' || $action == 'EditAccount'
		|| $action == 'ChangePassword' || $action == 'AddressBook'
		|| $action == 'DeleteAddress') 
			return $this->edit($params);
		else if ($action == 'PasswordForgotten') 
			return $this->passwordForgotten($params);
		else 
			return $this->query($params);
	}

	function validate(&$params)
	{
		$action = prepare_input($params['action']);

		$accountId = (int)$params['accountId'];
		if ($accountId < 0) $accountId = 0;

		$accountSession = prepare_input($params['accountSession']);
		if ($accountSession == null) $accountSession = '';

		$emailAddress = prepare_input($params['email_address']);
		if ($emailAddress == null) $emailAddress = '';

		$password = prepare_input($params['password']);
		if ($password == null) $password = '';

		$expiry = time() + $this->SESS_LIFE;

		$sql = 'delete from ' . TABLE_SESSIONS . ' where expiry < \'' . time() . '\'';
		mysql_query($sql) or die(mysql_error());

		$isAdministrator = false;
		
		//Logon Attempt
		if ($action == 'LoginAccount')
		{
			$sqlQuery = 'SELECT customers_id, customers_password from ' . TABLE_CUSTOMERS .
			' where customers_email_address=\''. mysql_real_escape_string($emailAddress) . '\' ' .
			' and customers_isLogin=1';
			$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
			$i = 0;
			while($row = mysql_fetch_array($dataReturned))
			{
				$accountId = (int)$row['customers_id'];
				$account_password = $row['customers_password'];
				$i++;
			}
					
			if ($i == 0)
			{
				$accountId = -10;
			}
			else if (!validate_password($password, $account_password))
			{
				$accountId = -20;
			}
			else
			{
				$accountSession = random_generator(32);
				$sql = 'insert into ' . TABLE_SESSIONS . ' (sesskey, expiry, value) values (\'' . $accountSession . '\',' . $expiry . ',' . $accountId . ')';
				mysql_query($sql) or die(mysql_error());
				$sql = "update " . TABLE_CUSTOMERS_INFO . " set customers_info_date_of_last_logon = now(), customers_info_number_of_logons = customers_info_number_of_logons+1 where customers_info_id = '" . $accountId . "'";
				mysql_query($sql) or die(mysql_error());
				$isAdministrator = isAdministrator($accountId);
			}
		}
		//Logged In validation
		else if ($accountId > 0)
		{
			$isAdministrator = isAdministrator($accountId);
				
			$sqlQuery = 'SELECT sesskey from ' . TABLE_SESSIONS .
			' where sesskey=\'' . mysql_real_escape_string($accountSession) . '\'' .
			' and value = \'' . mysql_real_escape_string($accountId) . '\'';

			$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
			$i = 0;
			while($row = mysql_fetch_array($dataReturned))
			{
				$i++;
			}
				
			if ($i == 0) //No Match
			{
				$accountId = -30;
				$accountSession = '';
			}
			else
			{
				$target_accountId = (int)$params['target_accountId'];
				if ($target_accountId > 0 && $isAdministrator) {
					$accountId = $target_accountId;
					$isAdministrator = isAdministrator($accountId);
					$accountSession = random_generator(32);
					$sql = 'insert into ' . TABLE_SESSIONS . ' (sesskey, expiry, value) values (\'' . $accountSession . '\',' . $expiry . ',' . $accountId . ')';
					mysql_query($sql) or die(mysql_error());
				}
				else {
					$sql = 'update ' . TABLE_SESSIONS . ' set expiry = \'' . $expiry . '\' where sesskey = \'' . $accountSession . '\'';
					mysql_query($sql) or die(mysql_error());
				}
			}
		}

		$value['accountId'] = $accountId;
		$value['accountSession'] = $accountSession;
		$value['isAdministrator'] = $isAdministrator;
		return $value;
	}

	function updateCart(&$params)
	{
		$accountId = (int)$params['accountId'];
		$cartJSON = prepare_input($params['cart']);
		$action = prepare_input($params['action']);
		if ($action == null) $action = '';

		if ($cartJSON != null && $cartJSON != '')
		{
			$cartArray = json_decode($cartJSON, true);
			if ($cartArray != null)
			{
				if ($accountId < 1)
				{
					//create temporary account for basket
					//used later to extract basket and send back.
					$accountId = rand(100, 999999999) * -1;
				}
				$products = $cartArray['cart'];
				if ($products != null)
				{
					$whereClause = ' where customers_id = \'' . $accountId . '\' and not (';
					foreach ($products as $product)
					{
						$productId = (int)$product['productId'];
						if ($productId > 0)
						{
							$quantity = (int)$product['quantity'];
							$options = $product['options'];
							$productIdFull = (string)$productId;
							if ($options != null)
							{
								foreach ($options as $option)
								{
									$optionsId = (int)$option['optionsId'];
									$optionsValuesId = (int)$option['optionsValuesId'];
									$productIdFull .= '{'.$optionsId.'}'.$optionsValuesId;
								}
							}
							$whereClause .= 'products_id = \'' . $productIdFull . '\' or ';
							$sqlQuery = 'select customers_basket_quantity from ' . TABLE_CUSTOMERS_BASKET . ' ' .
							'where customers_id = \'' . $accountId . '\' and products_id = \'' . mysql_real_escape_string($productIdFull) . '\'';

							$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
							$i = 0;
							$dbQuantity = $quantity;
							while($row = mysql_fetch_array($dataReturned))
							{
								$dbQuantity = (int)$row['customers_basket_quantity'];
								if ($action == 'LoginAccount')
								$quantity = $quantity + $dbQuantity;
								$i++;
							}
							if ($i == 0)
							{
								//insert
								$sql = 'insert into ' . TABLE_CUSTOMERS_BASKET . ' (customers_id, products_id, products_id_actual, customers_basket_quantity, customers_basket_date_added) ' .
								'values (\'' . $accountId . '\', \''. $productIdFull .'\',\''. $productId . '\',\''. $quantity .'\',\''. date('Ymd') . '\')';
								mysql_query($sql) or die(mysql_error());
								if ($options != null)
								{
									foreach ($options as $option)
									{
										$optionsId = $option['optionsId'];
										$optionsValuesId = $option['optionsValuesId'];
										$sql = 'insert into ' . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . ' (customers_id, products_id, products_options_id, products_options_value_id) ' .
										'values (\'' . $accountId . '\',\''. $productIdFull .'\',\''. $optionsId .'\',\''. $optionsValuesId .'\')';
										mysql_query($sql) or die(mysql_error());
									}
								}
							}
							else if ($i > 0 && $quantity != $dbQuantity)
							{
								//update
								$sql = 'update ' . TABLE_CUSTOMERS_BASKET . ' set customers_basket_quantity = ' . $quantity . ' ' .
								'where customers_id = \'' . $accountId . '\' and products_id = \'' . $productIdFull . '\'';
								mysql_query($sql) or die(mysql_error());
							}
						}
					}
					//Remove existing that are no longer in the Cart.
					if ($action != 'LoginAccount')
					{
						if (substr($whereClause, -4) == ' or ')
						$whereClause = substr($whereClause, 0, -4) .')';
						else
						$whereClause = substr($whereClause, 0, -10);

						$sql = 'delete from ' . TABLE_CUSTOMERS_BASKET . $whereClause;
						mysql_query($sql) or die(mysql_error());
						$sql = 'delete from ' . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . $whereClause;
						mysql_query($sql) or die(mysql_error());
					}
				}
			}
		}
		return $accountId;
	}

	function query(&$params)
	{
		$handle = get_class($this);
		$superHandle = $params['superHandle'];
		if ($superHandle != null && strlen($superHandle) > 0) $handle = $superHandle;

		$accountId = (int)$params['accountId'];
		$accountSession = prepare_input($params['accountSession']);
		if ($accountSession == null) $accountSession = '';

		$value{$handle . 'MetaData'}{'display_company'}= returnBoolean(ACCOUNT_COMPANY);
		$value{$handle . 'MetaData'}{'display_dob'}= returnBoolean(ACCOUNT_DOB);
		$value{$handle . 'MetaData'}{'display_gender'}= returnBoolean(ACCOUNT_GENDER);
		$value{$handle . 'MetaData'}{'display_state'}= returnBoolean(ACCOUNT_STATE);
		$value{$handle . 'MetaData'}{'display_suburb'}= returnBoolean(ACCOUNT_SUBURB);

		$value{$handle . 'MetaData'}{'entry_city_length_min'}= (int)ENTRY_CITY_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_dob_length_min'}= (int)ENTRY_DOB_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_email_address_length_min'}= (int)ENTRY_EMAIL_ADDRESS_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_email_address_format_check'}=returnBoolean(ENTRY_EMAIL_ADDRESS_FORMAT_CHECK);
		$value{$handle . 'MetaData'}{'entry_firstname_length_min'}= (int)ENTRY_FIRST_NAME_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_lastname_length_min'}= (int)ENTRY_LAST_NAME_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_password_length_min'}= (int)ENTRY_PASSWORD_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_postcode_length_min'}= (int)ENTRY_POSTCODE_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_state_length_min'}= (int)ENTRY_STATE_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_street_address_length_min'}= (int)ENTRY_STREET_ADDRESS_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'entry_telephone_length_min'}= (int)ENTRY_TELEPHONE_MIN_LENGTH;
		$value{$handle . 'MetaData'}{'address_book_entries_max'}= (int)MAX_ADDRESS_BOOK_ENTRIES;
		$value{$handle . 'MetaData'}{'require_administrator'}= returnBoolean(REQUIRE_ADMINISTRATOR);

		$sqlQuery = 'select c.countries_name, c.countries_iso_code_2, c.countries_iso_code_3, f.address_format, f.address_summary ' .
		'from ' . TABLE_COUNTRIES . ' c, ' . TABLE_ADDRESS_FORMAT . ' f ' .
		'where c.address_format_id=f.address_format_id ' . 
		'order by c.countries_name';
		$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
		$i = 0;
		while($row = mysql_fetch_array($dataReturned))
		{
			$value{$handle . 'MetaData'}{'countries'}{$i}{'name'}= $row['countries_name'];
			$value{$handle . 'MetaData'}{'countries'}{$i}{'iso_code_2'}= $row['countries_iso_code_2'];
			$value{$handle . 'MetaData'}{'countries'}{$i}{'iso_code_3'}= $row['countries_iso_code_3'];
			$value{$handle . 'MetaData'}{'countries'}{$i}{'address_format'}= $row['address_format'];
			$value{$handle . 'MetaData'}{'countries'}{$i}{'address_summary'}= $row['address_summary'];
			$i++;
		}

		$sqlQuery = 'select z.zone_code, z.zone_name, c.countries_name, c.countries_iso_code_2, c.countries_iso_code_3 ' .
		'from ' . TABLE_ZONES . ' z, ' . TABLE_COUNTRIES . ' c ' .
		'where c.countries_id=z.zone_country_id ' .
		'order by c.countries_name, z.zone_name';
		$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
		$i = 0;
		while($row = mysql_fetch_array($dataReturned))
		{
			$value{$handle . 'MetaData'}{'zones'}{$i}{'name'}= $row['zone_name'];
			$value{$handle . 'MetaData'}{'zones'}{$i}{'code'}= $row['zone_code'];
			$value{$handle . 'MetaData'}{'zones'}{$i}{'country'}= $row['countries_name'];
			$i++;
		}

		if ($accountId > 0)
		{
			$sqlQuery = 'select customers_id, customers_gender, customers_firstname, customers_lastname, ' .
                        "DATE_FORMAT(customers_dob, '%Y-%m-%d %H:%i:%s') as dob, customers_email_address, " .
			'customers_default_address_id, customers_telephone, customers_fax, customers_newsletter, customers_isWholesale, customers_isLogin '.
			'from ' . TABLE_CUSTOMERS . ' ' .
			'where customers_id=\'' . $accountId . '\'';
			$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
			$i = 0;
			while($row = mysql_fetch_array($dataReturned))
			{
				$id = (int)$row['customers_id'];
				$default_addressId = (int)$row['customers_default_address_id'];

				$value{$handle}{$i}{'id'}= $id;
				$value{$handle}{$i}{'session'} = $accountSession;
				$value{$handle}{$i}{'gender'}= $row['customers_gender'];
				$value{$handle}{$i}{'firstname'}= $row['customers_firstname'];
				$value{$handle}{$i}{'lastname'}= $row['customers_lastname'];
				$value{$handle}{$i}{'dob'}= $row['dob'];
				$value{$handle}{$i}{'email_address'}= $row['customers_email_address'];
				$value{$handle}{$i}{'telephone'}= $row['customers_telephone'];
				$value{$handle}{$i}{'fax'}= $row['customers_fax'];
				$value{$handle}{$i}{'newsletter'}= (boolean)$row['customers_newsletter'];
				$value{$handle}{$i}{'wholesale'}= (boolean)$row['customers_isWholesale'];
				$value{$handle}{$i}{'isLogin'}=(boolean)$row['customers_isLogin'];
				$value{$handle}{$i}{'error_code'}= (int)$params['accountErrorCode'];

				$value{$handle}{$i}{'addresses'} = getAddresses($accountId, $default_addressId);

				$subParams['handle'] = 'Cart';
				$subParams['accountId'] = $accountId;
				$subParams['languageId'] = (int)$params['languageId'];
				$subParams['max_rows'] = MAX_QTY_IN_CART;
				$subParams['searchCart'] = true;

				require_once('includes/components/ProductsSearchSubComponent.php');
				$subComponent = new ProductsSearchSubComponent();
				$return = $subComponent->query($subParams);
				if ($return != null)
				{
					$value{$handle . 'MetaData'}{'cart_meta_data'} = $return['CartMetaData'];
					$value{$handle}{$i}{'cart'} = $return['Cart'];
				}

				$sqlQuery1 = 'select r.roles_name ' .
				'from ' . TABLE_ROLES . ' r, ' . TABLE_ROLES_TO_CUSTOMERS . ' rc ' .
				'where r.roles_id=rc.roles_id and rc.customers_id=' . $accountId . ' ' .
				'order by r.roles_name';
				$dataReturned1 = mysql_query($sqlQuery1) or die(mysql_error());
				$j = 0;
				while($row1 = mysql_fetch_array($dataReturned1))
				{
					$role = $row1['roles_name'];
					$value{$handle}{$i}{'roles'}{$j}{'name'}= $role;

					if ($role == 'administrator') {
						$value{$handle . 'MetaData'}{'admin_url'}= ADMIN_URL;
					}

					$j++;
				}

				$i++;
			}
		}
		else
		{
			$gender = prepare_input($params['gender']);
			$firstname = prepare_input($params['firstname']);
			$lastname = prepare_input($params['lastname']);
			$dob = (int)$params['dob'];
			$dob = (int)$dob/1000.00;
			$emailAddress = prepare_input($params['email_address']);
			$company = prepare_input($params['company']);
			$streetAddress = prepare_input($params['street_address']);
			$suburb = prepare_input($params['suburb']);
			$postcode = prepare_input($params['postcode']);
			$city = prepare_input($params['city']);
			$state = prepare_input($params['state']);
			$country = prepare_input($params['country']);
			$telephone = prepare_input($params['telephone']);
			$fax = prepare_input($params['fax']);
			$newsletter = 0;
			$newsletterIn = prepare_input($params['newsletter']);
			if ($newsletterIn != null && $newsletter == 'on') $newsletter = 1;
			$basketAccountId = (int)$params['basketAccountId'];

			if ($gender == null) $gender = '';
			if ($firstname == null) $firstname = '';
			if ($lastname == null) $lastname = '';
			if ($emailAddress == null) $emailAddress = '';
			if ($company == null) $company = '';
			if ($streetAddress == null) $streetAddress = '';
			if ($suburb == null) $suburb = '';
			if ($postcode == null) $postcode = '';
			if ($city == null) $city = '';
			if ($state == null) $state = '';
			if ($country == null) $country = '';
			if ($telephone == null) $telephone = '';
			if ($fax == null) $fax = '';

			$dobDate = date('Y-m-d 00:00:00',$dob);

			if ($accountId == 0)
			{
				$newsletter = 1;

				$sqlQuery = 'select c.countries_name ' .
				'from ' . TABLE_ZONES . ' z, ' . TABLE_COUNTRIES . ' c ' .
				'where c.countries_id=z.zone_country_id ' .
				'and zone_id = ' . STORE_ZONE . ' ' .
				'group by c.countries_name';

				$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
				$i = 0;
				while($row = mysql_fetch_array($dataReturned))
				{
					$country = $row['countries_name'];
				}
				$dobDate = null;
			}

			$value{$handle}{0}{'id'}= $accountId;
			$value{$handle}{0}{'session'} = '';
			$value{$handle}{0}{'gender'}= $gender;
			$value{$handle}{0}{'firstname'}= $firstname;
			$value{$handle}{0}{'lastname'}= $lastname;
			$value{$handle}{0}{'dob'}= $dobDate;
			$value{$handle}{0}{'email_address'}= $emailAddress;
			$value{$handle}{0}{'telephone'}= $telephone;
			$value{$handle}{0}{'fax'}= $fax;
			$value{$handle}{0}{'newsletter'}= (boolean)$newsletter;
			$value{$handle}{0}{'wholesale'}= false;
			$value{$handle}{0}{'isLogin'}=false;
			$value{$handle}{0}{'error_code'}= (int)$params['accountErrorCode'];
			$value{$handle}{0}{'addresses'}{0}{'default'}= true;
			$value{$handle}{0}{'addresses'}{0}{'id'}= $accountId;
			$value{$handle}{0}{'addresses'}{0}{'gender'}= $gender;
			$value{$handle}{0}{'addresses'}{0}{'company'}= $company;
			$value{$handle}{0}{'addresses'}{0}{'firstname'}= $firstname;
			$value{$handle}{0}{'addresses'}{0}{'lastname'}= $lastname;
			$value{$handle}{0}{'addresses'}{0}{'street_address'}= $streetAddress;
			$value{$handle}{0}{'addresses'}{0}{'suburb'}= $suburb;
			$value{$handle}{0}{'addresses'}{0}{'postcode'}= $postcode;
			$value{$handle}{0}{'addresses'}{0}{'city'}= $city;
			$value{$handle}{0}{'addresses'}{0}{'state'}= $state;
			$value{$handle}{0}{'addresses'}{0}{'country'}= $country;

			//Get temporary basket
			$subParams['handle'] = 'Cart';
			$subParams['accountId'] = $basketAccountId;
			$subParams['languageId'] = (int)$params['languageId'];
			$subParams['max_rows'] = MAX_QTY_IN_CART;
			$subParams['searchCart'] = true;

			require_once('includes/components/ProductsSearchSubComponent.php');
			$subComponent = new ProductsSearchSubComponent();
			$return = $subComponent->query($subParams);
			if ($return != null)
			{
				$value{$handle . 'MetaData'}{'cart_meta_data'} = $return['CartMetaData'];
				$value{$handle}{0}{'cart'} = $return['Cart'];
			}

		}

		return $value;
	}

	function edit(&$params)
	{
		$display_company = returnBoolean(ACCOUNT_COMPANY);
		$display_dob = returnBoolean(ACCOUNT_DOB);
		$display_gender = returnBoolean(ACCOUNT_GENDER);
		$display_state = returnBoolean(ACCOUNT_STATE);
		$display_suburb = returnBoolean(ACCOUNT_SUBURB);
		$entry_city_length_min = (int)ENTRY_CITY_MIN_LENGTH;
		$entry_email_address_length_min = (int)ENTRY_EMAIL_ADDRESS_MIN_LENGTH;
		$entry_firstname_length_min = (int)ENTRY_FIRST_NAME_MIN_LENGTH;
		$entry_lastname_length_min = (int)ENTRY_LAST_NAME_MIN_LENGTH;
		$entry_password_length_min = (int)ENTRY_PASSWORD_MIN_LENGTH;
		$entry_postcode_length_min = (int)ENTRY_POSTCODE_MIN_LENGTH;
		$entry_state_length_min = (int)ENTRY_STATE_MIN_LENGTH;
		$entry_street_address_length_min = (int)ENTRY_STREET_ADDRESS_MIN_LENGTH;
		$entry_telephone_length_min = (int)ENTRY_TELEPHONE_MIN_LENGTH;
		$address_book_entries_max = (int)MAX_ADDRESS_BOOK_ENTRIES;

		$action = prepare_input($params['action']);
		$accountId = (int)$params['accountId'];
		$addressId = (int)$params['addressId'];

		$dump = (int)$params['dump'];

		$gender = prepare_input($params['gender']);
		$firstname = prepare_input($params['firstname']);
		$lastname = prepare_input($params['lastname']);
		$dob = (int)$params['dob'];
		$dob = (int)$dob/1000.00;
		$emailAddress = prepare_input($params['email_address']);
		$company = prepare_input($params['company']);
		$streetAddress = prepare_input($params['street_address']);
		$suburb = prepare_input($params['suburb']);
		$postcode = prepare_input($params['postcode']);
		$city = prepare_input($params['city']);
		$state = prepare_input($params['state']);
		$country = prepare_input($params['country']);
		$telephone = prepare_input($params['telephone']);
		$fax = prepare_input($params['fax']);
		$newsletter = (int)$params['newsletter'];
		$password = prepare_input($params['password']);

		if ($gender == null) $gender = '';
		if ($firstname == null) $firstname = '';
		if ($lastname == null) $lastname = '';
		if ($emailAddress == null) $emailAddress = '';
		if ($company == null) $company = '';
		if ($streetAddress == null) $streetAddress = '';
		if ($suburb == null) $suburb = '';
		if ($postcode == null) $postcode = '';
		if ($city == null) $city = '';
		if ($state == null) $state = '';
		if ($country == null) $country = '';
		if ($telephone == null) $telephone = '';
		if ($fax == null) $fax = '';
		if ($password == null) $password = '';


		if ($action == 'CreateAccount')
		{
			//CAPTCHA
			require_once('includes/components/CaptchaComponent.php');
			$isCaptchaCodeValid = validateCaptchaCode($params);

			if ($isCaptchaCodeValid == -1) {$params['accountErrorCode'] = -35; return $this->query($params);}
			if ($isCaptchaCodeValid == -2) {$params['accountErrorCode'] = -36; return $this->query($params);}
			if ($isCaptchaCodeValid == -3) {$params['accountErrorCode'] = -37; return $this->query($params);}
			if ($isCaptchaCodeValid == -4) {$params['accountErrorCode'] = -38; return $this->query($params);}
		}

		$required_fields_available = true;
		if ($required_fields_available && ($accountId == 0 || strlen($gender) > 0) && $display_gender && !($gender == 'm' || $gender == 'f')) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -40; return $this->query($params);}
		if ($required_fields_available && ($accountId == 0 || strlen($firstname) > 0) && strlen($firstname) < $entry_firstname_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -41; return $this->query($params);}
		if ($required_fields_available && ($accountId == 0 || strlen($lastname) > 0) && strlen($lastname) < $entry_lastname_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -42; return $this->query($params);}

		if ($required_fields_available && ($accountId == 0 || strlen($emailAddress) > 0) && (strlen($emailAddress) < $entry_email_address_length_min || !validate_email_format($emailAddress))) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -43; return $this->query($params);}

		if ($required_fields_available && ($accountId == 0 || strlen($streetAddress) > 0) && strlen($streetAddress) < $entry_street_address_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -44; return $this->query($params);}
		if ($required_fields_available && ($accountId == 0 || strlen($postcode) > 0) && strlen($postcode) < $entry_postcode_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -45; return $this->query($params);}
		if ($required_fields_available && ($accountId == 0 || strlen($city) > 0) && strlen($city) < $entry_city_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -46; return $this->query($params);}
		if ($required_fields_available && ($accountId == 0 || strlen($state) > 0) && $display_state && strlen($state) < $entry_state_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -47; return $this->query($params);}
		if ($required_fields_available && ($accountId == 0 || strlen($telephone) > 0) && strlen($telephone) < $entry_telephone_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -48; return $this->query($params);}
		if ($required_fields_available && ($accountId == 0 || strlen($password) > 0) && strlen($password) < $entry_password_length_min) $required_fields_available = false;
		if (!$required_fields_available) {$params['accountErrorCode'] = -49; return $this->query($params);}

		$exists = false;
		$sqlQuery = 'select customers_id, customers_isLogin, customers_default_address_id from ' . TABLE_CUSTOMERS . 
		' where customers_email_address = \'' . mysql_real_escape_string($emailAddress) . '\'';
		if ($accountId > 0) $sqlQuery = 'select customers_id from ' . TABLE_CUSTOMERS . ' where customers_id = \'' . $accountId . '\'';
		$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
		$i = 0;
		$isLogin = false;
		while($row = mysql_fetch_array($dataReturned))
		{
			$db_accountId = (int)$row['customers_id'];
			$isLogin = (boolean)$row['customers_isLogin'];
			$db_default_address_id = (int)$row['customers_default_address_id'];
			$i++;
			break;
		}
		if ($i > 0) $exists = true;

		if ($accountId == 0 && $exists && $isLogin)
		{
			$params['accountErrorCode'] = -50;
			return $this->query($params);
		}
		else if ($accountId > 0 && !$exists)
		{
			$params['accountErrorCode'] = -60;
			return $this->query($params);
		}
		else if ($accountId > 0 && $exists && $accountId != $db_accountId)
		{
			$params['accountErrorCode'] = -70;
			return $this->query($params);
		}
		if ($db_accountId > 0) $accountId = $db_accountId;

		$country_id = 0;
		$zone_id = 0;
		if (strlen($country) > 0)
		{
			$sqlQuery = 'select countries_id from . ' . TABLE_COUNTRIES . ' where countries_name = \'' . mysql_real_escape_string($country) . '\'';
			$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
			while($row = mysql_fetch_array($dataReturned))
			{
				$country_id = (int)$row['countries_id'];
				break;
			}
			if ($display_state && strlen($state) > 0)
			{
				$sqlQuery = 'select zone_id from ' . TABLE_ZONES . ' ' .
				'where zone_country_id = ' . $country_id . ' and zone_code = \'' . mysql_real_escape_string($state) . '\'';
				$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
				while($row = mysql_fetch_array($dataReturned))
				{
					$zone_id = $row['zone_id'];
				}
			}
		}

		//Update or Insert into Accounts Table.
		$sql_data_array = array();
		if (strlen($firstname) > 0) $sql_data_array['customers_firstname'] = $firstname;
		if (strlen($lastname) > 0)  $sql_data_array['customers_lastname'] = $lastname;
		if (strlen($emailAddress) > 0)  $sql_data_array['customers_email_address'] = $emailAddress;
		if (strlen($telephone) > 0)  $sql_data_array['customers_telephone'] = $telephone;
		if (strlen($fax) > 0)  $sql_data_array['customers_fax'] = $fax;
		if ($action == 'CreateAccount') $sql_data_array['customers_newsletter'] = $newsletter;
		if (strlen($password) > 0)  $sql_data_array['customers_password'] = encrypt_password($password);

		if ($display_gender && strlen($gender) > 0) $sql_data_array['customers_gender'] = $gender;
		if ($display_dob && $dob != 0) $sql_data_array['customers_dob'] = date('Ymd',$dob);
		$sql_data_array['customers_isLogin'] = 1;

		$accountInserted = false;
		$accountEdited = false;

		if ($action == 'CreateAccount' || $action == 'EditAccount' || $action == 'ChangePassword')
		{
			$sqlAction = 'insert';
			$where = '';
			if ($accountId > 0)
			{
				$sqlAction = 'update';
				$where = 'customers_id='.$accountId;
			}

			if (count($sql_data_array) > 0)
			{
				db_perform(TABLE_CUSTOMERS, $sql_data_array, $sqlAction, $where);
				if ($sqlAction == 'insert') {
					$accountInserted = true;
					$accountId = mysql_insert_id();
				}
				else {
					$accountEdited = true;
				}
			}
		}
		
		if ($action == 'CreateAccount' && $exists && !$isLogin) {
			$addressId = $db_default_address_id;
		}

		//Insert or Update the Address (maybe)
		$sqlAction = 'insert';
		if ($addressId > 0)
		{
			$sqlAction = 'update';

			//Does the Address Entry Exist?
			$sqlQuery = 'select address_book_id from ' . TABLE_ADDRESS_BOOK .
			' where address_book_id = ' . $addressId . ' and customers_id = ' . $accountId;
			$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
			$i = 0;
			while($row = mysql_fetch_array($dataReturned))
			{
				$i++;
				break;
			}
			if ($i == 0)
			{
				$params['accountErrorCode'] = -80;
				return $this->query($params);
			}
		}

		if ($action == 'DeleteAddress' && $addressId > 0)
		{
			//Don't delete primary address
			$defaultAddressId = 0;
			$sqlQuery = 'select customers_default_address_id from ' . TABLE_CUSTOMERS . ' where customers_id = ' . $accountId;
			$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
			while($row = mysql_fetch_array($dataReturned))
			{
				$defaultAddressId = (int)$row['customers_default_address_id'];
				break;
			}
			if ($defaultAddressId == $addressId)
			{
				$params['accountErrorCode'] = -85;
				return $this->query($params);
			}

			$sql = 'delete from ' . TABLE_ADDRESS_BOOK . ' where address_book_id = ' . $addressId;
			mysql_query($sql) or die(mysql_error());
			return $this->query($params);
		}

		if ($action == 'AddressBook' && $sqlAction == 'insert')
		{
			//Would adding this address mean too many?
			$sqlQuery = 'select address_book_id from ' . TABLE_ADDRESS_BOOK . ' where customers_id = ' . $accountId;
			$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
			$i = 0;
			while($row = mysql_fetch_array($dataReturned))
			{
				$i++;
			}
			if ($i > ($address_book_entries_max -1))
			{
				$params['accountErrorCode'] = -90;
				return $this->query($params);
			}
		}

		if ($action == 'CreateAccount' || $action == 'AddressBook')
		{
			$sql_data_array = array();
			if ($sqlAction == 'insert') $sql_data_array['customers_id'] = $accountId;
			if (strlen($firstname) > 0) $sql_data_array['entry_firstname'] = $firstname;
			if (strlen($lastname) > 0)  $sql_data_array['entry_lastname'] = $lastname;
			if (strlen($streetAddress) > 0)  $sql_data_array['entry_street_address'] = $streetAddress;
			if (strlen($postcode) > 0)  $sql_data_array['entry_postcode'] = $postcode;
			if (strlen($city) > 0)  $sql_data_array['entry_city'] = $city;
			if ($country_id > 0)  $sql_data_array['entry_country_id'] = $country_id;

			if ($display_gender && strlen($gender) > 0) $sql_data_array['entry_gender'] = $gender;
			if ($display_company && strlen($company) > 0) $sql_data_array['entry_company'] = $company;
			if ($display_suburb && strlen($suburb) > 0) $sql_data_array['entry_suburb'] = $suburb;

			if ($display_state)
			{
				if ($zone_id > 0)
				{
					$sql_data_array['entry_zone_id'] = $zone_id;
					$sql_data_array['entry_state'] = '';
				}
				else if (strlen($state) > 0)
				{
					$sql_data_array['entry_zone_id'] = '0';
					$sql_data_array['entry_state'] = $state;
				}
			}

			if ($sqlAction == 'update') $where = 'address_book_id = ' . $addressId;

			db_perform(TABLE_ADDRESS_BOOK, $sql_data_array, $sqlAction, $where);

			if ($sqlAction == 'insert') $addressId = mysql_insert_id();
		}

		if ($accountInserted) {
			$sql = 'update ' . TABLE_CUSTOMERS . ' set customers_default_address_id = \'' . (int)$addressId . '\' where customers_id = \'' . (int)$accountId . '\'';
			mysql_query($sql) or die(mysql_error());

			$sql = 'insert into ' . TABLE_CUSTOMERS_INFO . ' (customers_info_id, customers_info_number_of_logons, customers_info_date_account_created) values (\'' . $accountId . '\', \'0\', now())';
			mysql_query($sql) or die(mysql_error());
		}

		if ($action == 'CreateAccount') {
			$name = $firstname . ' ' . $lastname;
			$email_text = sprintf(EMAIL_GREET_NONE, $firstname);
			$email_text .= EMAIL_WELCOME . EMAIL_TEXT . EMAIL_CONTACT . EMAIL_WARNING;
			send_email($name, $emailAddress, EMAIL_SUBJECT, $email_text, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
			
			$params['accountId'] = $accountId;

			$accountSession = random_generator(32);
			$params['accountSession'] = $accountSession;

			$expiry = time() + $this->SESS_LIFE;

			$sql = 'delete from ' . TABLE_SESSIONS . ' where expiry < \'' . time() . '\'';
			mysql_query($sql) or die(mysql_error());

			$sql = 'insert into ' . TABLE_SESSIONS . ' (sesskey, expiry, value) values (\'' . $accountSession . '\',' . $expiry . ',' . $accountId . ')';
			mysql_query($sql) or die(mysql_error());

			//Newsletter Modules
			if ($newsletter == 1 && defined('MODULE_NEWSLETTER_INSTALLED') && MODULE_NEWSLETTER_INSTALLED != null)
			{
				$newsletterParams['gender'] = $gender;
				$newsletterParams['firstname'] = $firstname;
				$newsletterParams['lastname'] = $lastname;
				$newsletterParams['dob'] = $dob;
				$newsletterParams['emailAddress'] = $emailAddress;
				$newsletterParams['telephone'] = $telephone;
				$newsletterParams['company'] = $company;
				$newsletterParams['postcode'] = $postcode;
				$newsletterParams['streetAddress'] = $streetAddress;
				$newsletterParams['city'] = $city;
				$newsletterParams['state'] = $state;
				$newsletterParams['country'] = $country;
		
				$modules = explode(';', MODULE_NEWSLETTER_INSTALLED);
				reset($modules);
				$i = 0;					
				while (list(, $value) = each($modules)) 
				{
					include_once('includes/modules/newsletter/' . $value);
					$class = substr($value, 0, strrpos($value, '.'));
					$obj = new $class;
					if ($obj != null && $obj->enabled)
					{
						$obj->process($newsletterParams);
						$i++;
					}
				}
			}
		}
		else if ($accountEdited) {
			$sql = 'update ' . TABLE_CUSTOMERS_INFO . ' set customers_info_date_account_last_modified=now() where customers_info_id=' . $accountId;
			mysql_query($sql) or die(mysql_error());
		}

		$params['accountErrorCode'] = 1;
		return $this->query($params);
	}


	function passwordForgotten(&$params)
	{
		$entry_email_address_length_min = (int)ENTRY_EMAIL_ADDRESS_MIN_LENGTH;
		$emailAddress = prepare_input($params['email_address']);
		if ($emailAddress == null) $emailAddress = '';

		$exists = false;
		$sqlQuery = 'select customers_id from ' . TABLE_CUSTOMERS . ' where customers_email_address = \'' . mysql_real_escape_string($emailAddress) . '\' ' .
		'and customers_isLogin=1';
		$dataReturned = mysql_query($sqlQuery) or die(mysql_error());
		$i = 0;
		while($row = mysql_fetch_array($dataReturned))
		{
			$db_accountId = (int)$row['customers_id'];
			$i++;
			break;
		}
		if ($i > 0) $exists = true;

		if (!$exists)
		{
			$params['accountErrorCode'] = -120;
			return $this->query($params);
		}
		
		$password = random_generator(7);
		$sql = 'update ' . TABLE_CUSTOMERS . ' set customers_password = \'' . encrypt_password($password) . '\' ' . 
			'where customers_email_address = \'' . mysql_real_escape_string($emailAddress) . '\'';
		mysql_query($sql) or die(mysql_error());

		$sql = 'update ' . TABLE_CUSTOMERS_INFO . ' set customers_info_date_account_last_modified=now() where customers_info_id=' . $db_accountId;
		mysql_query($sql) or die(mysql_error());

		$ip = $_SERVER['REMOTE_ADDR'];
		$email_text = sprintf(EMAIL_PASSWORD_REMINDER_BODY, $ip, $password);
		$email_text .= EMAIL_CONTACT;
		send_email($name, $emailAddress, EMAIL_PASSWORD_REMINDER_SUBJECT, $email_text, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);

		$params['accountErrorCode'] = -100;
		return $this->query($params);
	}
}
?>
